/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.Arsanesia.TempleRush.Controllers;


import java.util.Random;

import com.Arsanesia.TempleRush.Enumeration.GeenieEnumeration;
import com.Arsanesia.TempleRush.Enumeration.Notif;
import com.Arsanesia.TempleRush.Models.Block;
import com.Arsanesia.TempleRush.Models.GeenieManager;
import com.Arsanesia.TempleRush.Models.Notification;
import com.Arsanesia.TempleRush.Models.Scenery;
import com.Arsanesia.TempleRush.Models.Smoke;
import com.Arsanesia.TempleRush.Models.Temple;
import com.Arsanesia.TempleRush.Views.Screens.AbstractScreen;
import com.Arsanesia.TempleRush.Views.Screens.Components.PopUp.Tutorial;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.flurry.android.FlurryAgent;



/**
 *
 * @author Chairul Ichsan
 */
public class World{

    public static final float WIDTH = 36;
    public static final float HEIGHT = 64;
    public static final int SCORE_FONT_SIZE = 20;
    public static final int TEXT_FONT_SIZE = 12;
    public static final float XGRID_SIZE = 6.6f;
    public static final float MARGIN = 3.8f;
    public static final int MAX_JIN_IN_WORLD = 5;
    public static final long TARGET_TIME = 150000;
    public static final int SMOKE_TIME = 6000;
    public static final int COMBO_TIME = 3000;
    public static final float FINISH_TIME = 3;
    public static final float PLUS_TIME = 10;
    public static final int LINE1_HEIGHT = 10;
    public static final int LINE2_HEIGHT = 55;
    public static final int LINE3_HEIGHT = 100;
    public static final int STATE_RUNNING = 0;
    public static final int STATE_FINISH = 1;
    public static final int STATE_GAME_OVER = 2;
    public static final float COMBO_RESET = 3;
    public static final float NOTIF_TIME = 1;
    private final float POINTER_TOPMARGIN = 170;
    private final float POINTER_DEFAULTY = AbstractScreen.VIEWPORT_DEFAULTHEIGHT - POINTER_TOPMARGIN;
    private final float POINTER_LEFTMARGIN = 10;
    private final float BAR_DEFAULTY = POINTER_DEFAULTY+80;
    
    
    private boolean worldReady = false;
    
    private static World self;
    
    private int level;
    private int score;
    private int countHit[] = {0, 0, 0};
    private int state;
    private int comboCount;
    private long playTime;
    private long prevTime;
    private long comboTime;
    private Temple temple;
    private GeenieManager geenieManager;
    private Notification notif;
    private float defaultmoonY;
    private Smoke smoke;
    private Scenery scene;
    private int[] countTappedGeenie;
    private int tapcount;

    private boolean gameover;
    private int lineSmoke;    
    private boolean isNotif;
    private boolean isSmoke;
    private Image templeGlow;
    private Image timeBar;
    private Image timePointer;
    private float pointerposition;
    private boolean istutor;
    private GeenieEnumeration tutorType;
    private Tutorial tutorial;

    
//    private Sprite timePointer;
    
    public static World getInstance(){
    	return self;
    }

    public World(TextureAtlas atlas) {
        Gdx.app.log(this.getClass().getSimpleName(), "creating the world");
    	level = 0;
        score = 0;
        state = World.STATE_RUNNING;
        gameover = false;
        istutor = false;
        comboCount = 0;

        isNotif = false;
        isSmoke = false;

//        initAsset();
        initComponent(atlas);
        worldReady = true;
        
        //geenie type from red until yellow
        countTappedGeenie = new int[9];
        
        pointerposition = POINTER_DEFAULTY;
        
    }
    public GeenieManager getGeenieManager(){
    	return this.geenieManager;
    }
    public int getScore(){
    	return this.score;
    }
    public Notification getNotif(){
    	return notif;
    }
    public int getTapCount(){
    	return tapcount;
    }
    
    public boolean isWorldReady(){
    	return worldReady;
    }
    public boolean isGameOver(){
    	return gameover;
    }
    public void togglePaused(){
    	this.worldReady = !this.worldReady;
    	//disable tutorial
    	if(istutor) {
    		istutor= !istutor;
    		geenieManager.setNewGeenieAdded(istutor);
    	}
    	this.prevTime = System.currentTimeMillis();
    }
    public boolean isSmoke(){
    	return isSmoke;
    }
    public Smoke getSmoke(){
    	return smoke;
    }
    public void gameOver() {
        //Game Over    
    	gameover = true;

    }
    public boolean isTutorMode(){
    	return istutor;
    }
    public GeenieEnumeration getTutorType(){
    	return tutorType;
    }

    public void incrementGeenieCountByType(GeenieEnumeration ge){
    	countTappedGeenie[ge.ordinal()]++;
    }
    public void incrementTapCount(){
    	tapcount++;
    }
    private void initComponent(TextureAtlas atlas) {
        prevTime = System.currentTimeMillis();
        
        templeGlow= new Image(new TextureRegion(atlas.createSprite("TEMPGLOW")));
        timePointer = new Image(new TextureRegion(atlas.createSprite("timebarpointer")));
        timeBar= new Image(new TextureRegion(atlas.createSprite("timebar")));
        notif = new Notification(atlas);

		//create the game scene
		scene = new Scenery(atlas);
		//create the temple
        temple = new Temple(atlas);
        temple.generateTemple(level);
        
        
        Gdx.app.log(this.getClass().getSimpleName(), "init geeniemanager");
    	geenieManager = new GeenieManager(atlas, this);
        geenieManager.spawnGeenie(level, temple.getAvailableColor());
        
        smoke = new Smoke(atlas);
        tutorial = new Tutorial(atlas);
        

    }
    public void addInternalComponents(Stage thestage){
    	scene.addSceneToStage(thestage);
    	//add temple
    	temple.addTempleToStage(thestage);
    	
    	//add the temple glow
    	thestage.addActor(templeGlow);
    	templeGlow.setPosition(Temple.LEFT_MARGIN-Block.WIDTH+10, Temple.BOTTOM_MARGIN - Block.HEIGHT - Temple.TEMPLE_HEIGHTADJUSTMENT-20);

    	//add moon
    	defaultmoonY = AbstractScreen.VIEWPORT_DEFAULTHEIGHT - scene.getMoon().getHeight();
    	scene.getMoon().setPosition( AbstractScreen.VIEWPORT_DEFAULTWIDTH - scene.getMoon().getWidth(), defaultmoonY);
    	
    	//add smoke background
    	smoke.addSmokeBackgroundToStage(thestage);
    	
    	//add geenies
    	geenieManager.addGeeniesToStage(thestage);
    	

    	//add other smoke
    	smoke.addSmokeToStage(thestage);
    	
    	//add timebar
    	thestage.addActor(timeBar);
    	timeBar.setPosition(POINTER_LEFTMARGIN+timePointer.getImageWidth()+5, BAR_DEFAULTY-timeBar.getHeight());
    	
    	thestage.addActor(timePointer);
    	timePointer.setPosition(POINTER_LEFTMARGIN, pointerposition);
    	
    	
    	

    	notif.addNotificationToStage(thestage);

    }
    public Temple getTemple(){
    	return this.temple;
    }
    public int getLevel(){
    	return this.level;
    }
    public int[] getTappedGeenieCount(){
    	return this.countTappedGeenie;
    }
    
    public void reset() {
        level = 0;
        score = 0;
        state = World.STATE_RUNNING;

        comboCount = 0;
        playTime = 0;
        prevTime = System.currentTimeMillis();
        
        isNotif = false;
        isSmoke = false;
        
        temple.generateTemple(level);
        geenieManager.resetGeenie();
        geenieManager.spawnGeenie(level, temple.getAvailableColor());
    }
    

    public void setIsNotif(boolean isNotif) {
        this.isNotif = isNotif;
    }

    private void combo() {
        comboTime = System.currentTimeMillis();
        ++comboCount;
    }

    private void levelUp() {
        /*
         * Increment level counter
         */
        ++level;
        FlurryAgent.logEvent("Level Up to level: "+(level+1)+"",true);
        /*
         * Reset time
         */
        float playRateTime = (float) playTime / (float) TARGET_TIME;

        if (playRateTime <= 0.2f) {
            playTime = 0;
        } else if (playRateTime >= 0.6f) {
            playTime -= TARGET_TIME / 2;
        } else {
            playTime -= TARGET_TIME / 5;
        }

        if (playTime < 0) {
            playTime = 0;
        }

        prevTime = System.currentTimeMillis();

        /*
         * Generate new temple
         */
        temple.generateTemple(level);

        /*
         * Reset geenie
         */
        geenieManager.resetGeenie();
        geenieManager.spawnGeenie(level, temple.getAvailableColor());
    }

    public void update() {
        /*
         * Update remaining time
         */
        playTime += System.currentTimeMillis() - prevTime;
        prevTime = System.currentTimeMillis();
        
        //update time pointer position
        float decremental =  playTime/1000;
        pointerposition = POINTER_DEFAULTY - decremental*1.5f;
        timePointer.setY(pointerposition);
        scene.getMoon().setY(defaultmoonY - decremental*2.2f);
        scene.decrementBgColor(decremental*0.01f/AbstractScreen.VIEWPORT_DEFAULTHEIGHT);
        if (playTime >= TARGET_TIME) {
            gameOver();
        	worldReady = false;
        }

        temple.update();

        geenieManager.update(this);

        if (isSmoke) {
            smoke.update();

        }

        if (comboCount > 0 && System.currentTimeMillis() - comboTime >= COMBO_TIME) {
            comboCount = 0;
        }

        /*
         * Check for finished temple
         */
        if (temple.getState() == Temple.STATE_FINISHED) {

            levelUp();
        }

        if (geenieManager.needSpawn()) {

            geenieManager.spawnGeenie(level, temple.getAvailableColor());
        }
    }

    public void startTutorMode(){
    	istutor= true;
    	worldReady = false;
    	tutorial.startTutorial(geenieManager.getNewGeenie());
    }
    
    public void drawTutorial(SpriteBatch sb, BitmapFont font){
    	tutorial.draw(sb,font);
    }
    public void checkTouch() {
        Notif templeHit;
        int geenieHit;

        geenieHit = geenieManager.getTouchedGeenieType();
        Gdx.app.log("geeniehit", geenieHit+"");
        if (geenieHit >= GeenieEnumeration.WHITE.ordinal()) {
        	/*if(geenieHit == GeenieEnumeration.BLACK.ordinal()){
        		 notif.setType(Notif.MISS);
                 temple.blackGeenieEffect();
        	}else*/ if (geenieHit == GeenieEnumeration.WHITE.ordinal()){
        		 if(timePointer.getY() < POINTER_DEFAULTY){
	        		 notif.setType(Notif.TIME);
	                 playTime -= 7000;
	                 combo();
	                 score += 7 * comboCount;
        		 }
        	}else if (geenieHit == GeenieEnumeration.GOLD.ordinal()){
        		 notif.setType(Notif.KING);
                 temple.kingGeenieEffect();
                 combo();
                 score += 15 * comboCount;        		
        	}else if (geenieHit == GeenieEnumeration.GREY.ordinal()){
        		 notif.setType(Notif.SMOKE);
                 isSmoke = true;
                 lineSmoke = new Random().nextInt(2);
                 smoke.startSmoke(lineSmoke == 0 ? AbstractScreen.VIEWPORT_DEFAULTHEIGHT - LINE1_HEIGHT : AbstractScreen.VIEWPORT_DEFAULTHEIGHT - LINE2_HEIGHT);
        	}

            isNotif = true;

        } else if (geenieHit != -1) {
            templeHit = temple.getNotifType();
            notif.setType(templeHit);
            isNotif = true;

            if (templeHit == Notif.MISS) {
                playTime += 5000;
            } else {
                combo();
                score += 3 * comboCount;
            }

            ++countHit[templeHit.ordinal()];
        }
    }
}
